/*!
 * \file Separator.h
 * \brief Clases Separator y EleccionClique
 *
 *  Created on: Jan 24, 2014
 *      Author: ik
 */

#ifndef SEPARATOR_H_
#define SEPARATOR_H_

#include <Proyectable.h>
#include <Desigualdad.h>
#include <Solucion.h>
#include <SeparatorParameters.h>
#include <CliquerGoloso.h>
#include <GeneradorClique.h>
#include <ProjectableVertexSet.h>
#include <Reserva.h>
#include <list>

using namespace std;

class Separator;

/*! \class Separator
 * \brief Clase que envolucra métodos usados para separar una solución no válida del problema de conjunto independiente máximo
 */
class Separator : public FactoryDesigualdad
{
private:
	int 					_n; //por comodidad;
	int						_iteration;
	bool					_proyeccionFuerte;
	int						_ncortes;
	int						_ncliques;
	int						_nrangos;
	int						_nprangos;
	int						_nllamadas;
	int						_rondasSinReserva;
	bool					_esReserva;
	Grafo&					_grafo;
	Grafo* 					_falso;
	Proyectable& 			_actual;
	GeneradorClique *		_eleccionClqFactory;
	list<Desigualdad*> 		_desigualdades;
	ProjectableCliqueSet * 	_clique;
	ProjectableCliqueSet * 	_lastClique;
	VertexSet * 			_cliqueados;
	VertexSet * 			_nocliqueados;
	VertexSet * 			_verticesRestantes;
	SeparatorParameters&	_parametros;
	int						_K;
	ReservaClique *			_reserva;
	double					_lastVal;
	int						_ninoperante;

	Cliquer *	_buscadorVioladas;
	Cliquer *	_calculadorLambda;

	Cliquer * createCliquer(TiposCliquer tipo, bool clqOrStab);
	int separarCliques(ProjectableCliqueSet& clique, Solucion &solucion, bool conRango);
	int separarRango(ProjectableCliqueSet& clique, Solucion &solucion);
	/*! \fn int separarLifteando(VertexSet& clique, Solucion &solucion, EleccionClique& eleccionClique)
	 * \brief Separa una solución proyectando y lifteando a partir de una clique
	 *
	 *
	 */
	Desigualdad * separarLifteando(ProjectableCliqueSet& clique, Solucion &solucion, GeneradorClique& eleccionClique);
	Desigualdad* desigualdadClique(ProjectableCliqueSet& clique);
	Desigualdad* buscarCliqueViolada(Solucion &solucion, ProjectableCliqueSet& clique);

public:
	Separator(Grafo &grafo, SeparatorParameters &parametros);
	virtual ~Separator();
	void restart();
	/*! \fn list<Desigualdad*>& separar(DoubleValueArray &solucion)
	 * \brief Ejecuta la separación de una solución especificada con proyecciones de cliques
	 *
	 * Este método usa una instancia de EleccionClique para enumerar cliques que son proyectadas y lifteadas. Las desigualdades violadas
	 * encontradas son agregadas a una lista.
	 *
	 * \param solucion Violada a separar.
	 * \return Una lista con las desigualdades violadas encontradas.
	 */
	virtual list<Desigualdad*>& separar(Solucion &solucion);
	virtual list<Desigualdad*>& separarReserva(Solucion &solucion);
	int getNVertices() { return _n; };
	int getCliques() { return _ncliques; };
	int getRangos() { return _nrangos; };
	int getPRangos() { return _nprangos; };
	int getNLlamadas() { return _nllamadas; };
	ReservaClique * getReservaCliques() {  return _reserva; };
};

#endif /* SEPARATOR_H_ */
